import { Injectable, EventEmitter } from '@angular/core';
import { PostMessageModule } from 'angular2-post-message/index';
import { GAOperation, GAMessage } from '../../models/ga.message';
import { AuthModel } from '../../models/auth.model';
import { environment } from '../../../environments/environment';

@Injectable()
export class GAService {
    //url for _UI front-end web app (may have different domain than back-end)
    public readonly containerUrl: string = environment.containerUrl;

    private static authObj: AuthModel = null;

    private static waitForAuth: boolean = false;

    private static listenerAdded: boolean = false;

    private static receivedAuth: EventEmitter<AuthModel> = new EventEmitter();

    constructor() {       
        if(!GAService.listenerAdded)
        {
            this.bindListener();
            GAService.listenerAdded = true;
        }
    }

    private bindListener(){        
        window.addEventListener('message', (message) => {
            if (message.origin == this.containerUrl) {                
                var object = JSON.parse(message.data);
                GAService.authObj = new AuthModel(
                    object.token,
                    object.userId,
                    object.accountId,
                    object.loginTime,
                    object.expiresIn
                );
                GAService.receivedAuth.emit(GAService.authObj);                                
            }
        });
    }

    //send connection request and get the auth_token as response
    public connect(): Promise<AuthModel> {        
        let promise = new Promise<AuthModel>((resolve, reject) => { 
            //wait for auth if needed
            if(GAService.waitForAuth == false)
            {               
                if (GAService.authObj != null && this.authExpired()) {
                    //refresh token                   
                    GAService.waitForAuth = true;
                    this.refreshToken();
                }   
                else if(GAService.authObj == null){
                    //connect
                    GAService.waitForAuth = true;
                    var message = new GAMessage(GAOperation.connect);
                    this.sendMessage(message);                
                }             
                else
                    resolve(GAService.authObj);                
            }

            if(GAService.waitForAuth == true)
            {
                GAService.receivedAuth.subscribe((authObj) => {   
                    if(GAService.waitForAuth) GAService.waitForAuth = false;
                    resolve(authObj);
                });
            }
        });

        return promise;
    }    
    private waitAuth(): Promise<AuthModel> {
        return new Promise<AuthModel>((resolve, reject) => {
            if (GAService.authObj == null) {
               
            }
            else
                resolve(GAService.authObj);
        });
    }

    private authExpired() {
        var now = new Date();
        var expires = new Date(Date.parse(GAService.authObj.loginTime));
        expires.setSeconds(expires.getSeconds() + GAService.authObj.expiresIn);
        return now > expires;
    }

    public disconnect(): void {
        GAService.authObj = null;
    }

    //send the content height to update the iFrame
    public resize(height: number): void {
        var message = new GAMessage(GAOperation.resize, height);
        this.sendMessage(message);
    }

    //send request to display preloader
    public showPreloader(): void {
        var message = new GAMessage(GAOperation.showPreloader);
        this.sendMessage(message);
    }

    //send request to hide preloader
    public hidePreloader(): void {
        var message = new GAMessage(GAOperation.hidePreloader);
        this.sendMessage(message);
    }

    //send request to add company to a portfolio
    public addToPortfolio(id: string, name: string, tickerExchange: string): void {
        var message = new GAMessage(GAOperation.addToPortfolio, { companyId: id, companyName: name, tickerExchange: tickerExchange });
        this.sendMessage(message);
    }

    //send request to download report
    public downloadReport(id: string, companyUrlFriendlyName: string, summary: boolean): void {
        var message = new GAMessage(GAOperation.downloadReport, {
            companyId: id,
            companyUrlFriendlyName: companyUrlFriendlyName,
            isSummaryReport: summary
        });
        this.sendMessage(message);
    }

    private refreshToken() {
        var message = new GAMessage(GAOperation.refreshToken);
        this.sendMessage(message);
    }

    private sendMessage(message: GAMessage): void {
        window.parent.postMessage(JSON.stringify(message), this.containerUrl);
    }
}
